package com.woniuxy.book.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniuxy.book.entity.BookInfo;
import com.woniuxy.book.entity.BookType;
import com.woniuxy.book.entity.PageInfo;
import com.woniuxy.book.exception.bookinfo.BookInfoException;
import com.woniuxy.book.exception.bookinfo.BookInfoExceptionCode;
import com.woniuxy.book.exception.booktype.BookTypeException;
import com.woniuxy.book.exception.booktype.BookTypeExceptionCode;
import com.woniuxy.book.mapper.BookInfoMapper;
import com.woniuxy.book.mapper.BookTypeMapper;
import com.woniuxy.book.param.bookinfo.AddBookInfoParam;
import com.woniuxy.book.param.bookinfo.SearchBookInfosParam;
import com.woniuxy.book.param.bookinfo.UpdateBookImageParam;
import com.woniuxy.book.param.bookinfo.UpdateBookInfoParam;
import com.woniuxy.book.service.BookInfoService;
import com.woniuxy.book.service.dto.BookInfoDTO;
import com.woniuxy.book.util.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author li
 * @since 2024年2月09日
 */
@Service
public class BookInfoServiceImpl implements BookInfoService {

    @Resource
    private BookTypeMapper bookTypeMapper;
    @Resource
    private BookInfoMapper bookInfoMapper;
    @Resource
    private OSSUtil ossUtil;

    @Resource
    private RedisUtil redisUtil;

    @Override
    @Transactional
    public void addBookInfo(AddBookInfoParam param) {
        //查询该书籍的类别是否存在
        BookType bookType = bookTypeMapper.selectById(param.getTypeId());
        if (bookType==null) {
            throw new BookTypeException(BookTypeExceptionCode.BOOK_TYPE_EXCEPTION_BOOKTYPE_NOT_EXISTS);
        }
        if (bookType.getTypeState()!= StateData.BOOK_TYPE_STATE_NORMAL) {
            throw new BookTypeException(BookTypeExceptionCode.BOOK_TYPE_EXCEPTION_BOOKTYPE_NOT_NORMAL);
        }
        //新增
        BookInfo bookInfo = BeanUtil.toBean(param, BookInfo.class);
        bookInfo.setTypeName(bookType.getTypeName());
        bookInfo.setBookState(StateData.BOOK_STATE_NORMAL);
        bookInfo.setFreeze(0);
        bookInfoMapper.insert(bookInfo);
    }

    @Override
    @Transactional
    public void updateBookImage(UpdateBookImageParam param) throws IOException {
        BookInfo bookInfo = bookInfoMapper.selectById(param.getBookId());
        if (bookInfo==null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_EXISTS);
        }
        //书籍是否被删除
        if (bookInfo.getBookState()== StateData.BOOK_STATE_DELETED) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_HAS_DELETED);
        }
        //上传图片
        String newPath = ossUtil.uploadFile(param.getImage().getInputStream(), param.getFileName(), "liucunyi");
        String path = FileNameUtil.getName(bookInfo.getBookImage());
        //删除原图片
        ossUtil.deleteFile("liucunyi",path);
        //修改数据库中的路径
        bookInfo.setBookImage(newPath);
        bookInfoMapper.updateById(bookInfo);
    }

    @Override
    public PageInfo searchBookInfos(SearchBookInfosParam param) {
        QueryWrapper<BookInfo> queryWrapper = new QueryWrapper<>();
        //判断作者
        if (ObjectUtil.isNotEmpty(param.getBookAuth())) {
            queryWrapper.like("book_auth",param.getBookAuth());
        }
        //判断出版社
        if (ObjectUtil.isNotEmpty(param.getBookPress())) {
            queryWrapper.like("book_press",param.getBookPress());
        }
        //判断展示名称
        if (ObjectUtil.isNotEmpty(param.getBookShowname())) {
            queryWrapper.like("book_showname",param.getBookShowname());
        }
        //判断书籍状态
        if (param.getBookState()!=null) {
            queryWrapper.eq("book_state",param.getBookState());
        }
        //判断出版起始日期
        if (ObjectUtil.isNotEmpty(param.getStartPressDate())) {
            queryWrapper.ge("press_date",param.getStartPressDate());
        }
        //判断出版最大日期
        if (ObjectUtil.isNotEmpty(param.getEndPressDate())) {
            queryWrapper.le("press_date",param.getEndPressDate());
        }
        //判断最小价格
        if (ObjectUtil.isNotEmpty(param.getMinPrice())) {
            queryWrapper.ge("book_price",param.getMinPrice());
        }
        //判断最大价格
        if (ObjectUtil.isNotEmpty(param.getMaxPrice())) {
            queryWrapper.le("book_price",param.getMaxPrice());
        }
        //判断类型
        if (ObjectUtil.isNotEmpty(param.getTypeId())) {
            ArrayList<Integer> children = new ArrayList<>();
            findChild(param.getTypeId(),children,null);
            children.add(param.getTypeId());
            queryWrapper.in("type_id",children);
        }
        queryWrapper.orderByAsc("book_id");
        Page<BookInfo> page = new Page<>(param.getPageNum() == null ? 1 : param.getPageNum(), param.getPageSize() == null ? 4 : param.getPageSize());
        bookInfoMapper.selectPage(page,queryWrapper);
        PageInfo pageInfo = BeanUtil.toBean(page, PageInfo.class);
        pageInfo.setPages(page.getPages());
        pageInfo.setList(page.getRecords());
        return pageInfo;
    }

    @Override
    public PageInfo selectBookInfos(SearchBookInfosParam param, String token) throws Exception {
        QueryWrapper<BookInfo> queryWrapper = new QueryWrapper<>();
        //一定是状态正常的书籍
        queryWrapper.eq("book_state",StateData.BOOK_STATE_NORMAL);
        //判断作者
        if (ObjectUtil.isNotEmpty(param.getBookAuth())) {
            queryWrapper.like("book_auth",param.getBookAuth());
        }
        //判断出版社
        if (ObjectUtil.isNotEmpty(param.getBookPress())) {
            queryWrapper.like("book_press",param.getBookPress());
        }
        //判断展示名称
        if (ObjectUtil.isNotEmpty(param.getBookShowname())) {
            queryWrapper.like("book_showname",param.getBookShowname());
        }
        //判断出版起始日期
        if (ObjectUtil.isNotEmpty(param.getStartPressDate())) {
            queryWrapper.ge("press_date",param.getStartPressDate());
        }
        //判断出版最大日期
        if (ObjectUtil.isNotEmpty(param.getEndPressDate())) {
            queryWrapper.le("press_date",param.getEndPressDate());
        }
        //判断最小价格
        if (ObjectUtil.isNotEmpty(param.getMinPrice())) {
            queryWrapper.ge("book_price",param.getMinPrice());
        }
        //判断最大价格
        if (ObjectUtil.isNotEmpty(param.getMaxPrice())) {
            queryWrapper.le("book_price",param.getMaxPrice());
        }
        //判断类型
        if (ObjectUtil.isNotEmpty(param.getTypeId())) {
            ArrayList<Integer> children = new ArrayList<>();
            findChild(param.getTypeId(),children,null);
            children.add(param.getTypeId());
            queryWrapper.in("type_id",children);
        }
        queryWrapper.orderByAsc("book_id");
        Page<BookInfo> page = new Page<>(param.getPageNum() == null ? 1 : param.getPageNum(), param.getPageSize() == null ? 8 : param.getPageSize());
        bookInfoMapper.selectPage(page,queryWrapper);
        PageInfo pageInfo = BeanUtil.toBean(page, PageInfo.class);
        List<BookInfoDTO> bookInfoDTOS = new ArrayList<>();
        for (BookInfo bookInfo : page.getRecords()) {
            BookInfoDTO bookInfoDTO = BeanUtil.toBean(bookInfo, BookInfoDTO.class);
            if ((token!=null)&&(!token.equals("null"))) {
                String refreshToken = redisUtil.get(token);
                if (refreshToken==null) {
                    throw new Exception("token无效 请重新登录");
                }
                Integer userId = (Integer) JWTUtil.getSubject(refreshToken);
                Set<String> set = redisUtil.revrange(RedisKeyUtil.collectBook(userId), 1, redisUtil.zsize(RedisKeyUtil.collectBook(userId)).intValue());

                if (set!=null) {
                    for (String bookId : set) {
                        if (bookId.equals(bookInfoDTO.getBookId()+"")) {
                            bookInfoDTO.setCollectState(1);
                        }
                    }
                }
            }
            bookInfoDTOS.add(bookInfoDTO);
        }
        pageInfo.setPages(page.getPages());
        pageInfo.setList(bookInfoDTOS);
        return pageInfo;
    }

    @Override
    public BookInfoDTO findBookInfoById(Integer bookId, String token) {
        BookInfo bookInfo = bookInfoMapper.selectById(bookId);
        BookInfoDTO bookInfoDTO = BeanUtil.toBean(bookInfo, BookInfoDTO.class);
        if (!token.equals("null")) {
            String refreshToken = redisUtil.get(token);
            Integer userId = (Integer) JWTUtil.getSubject(refreshToken);
            Set<String> set = redisUtil.revrange(RedisKeyUtil.collectBook(userId), 1, redisUtil.zsize(RedisKeyUtil.collectBook(userId)).intValue());
            if (set!=null) {
                for (String id : set) {
                    if (id.equals(bookId+"")) {
                        bookInfoDTO.setCollectState(1);
                    }
                }
            }
        }
        return bookInfoDTO;
    }

    //修改图书信息
    @Override
    @Transactional
    public void updateBookInfo(UpdateBookInfoParam param) {
        BookInfo bookInfo = bookInfoMapper.selectById(param.getBookId());
        if (bookInfo==null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_EXISTS);
        }
        if (bookInfo.getBookState()== StateData.BOOK_STATE_DELETED) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_HAS_DELETED);
        }
        BookType bookType = bookTypeMapper.selectById(param.getTypeId());
        param.setTypeName(bookType.getTypeName());
        BookInfo book = BeanUtil.toBean(param, BookInfo.class);
        bookInfoMapper.updateById(book);

    }

    @Override
    @Transactional
    public void updateBookState(Integer bookId, Integer bookState) {
        BookInfo bookInfo = bookInfoMapper.selectById(bookId);
        if (bookInfo==null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_EXISTS);
        }
        if (bookInfo.getBookState()== StateData.BOOK_STATE_DELETED) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_HAS_DELETED);
        }
        if (bookState== StateData.BOOK_STATE_DISABLED) {
            if (bookInfo.getBookState()== StateData.BOOK_STATE_DISABLED) {
                throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_HAS_DISABLED);
            }
        }
        if (bookState== StateData.BOOK_STATE_NORMAL&&bookInfo.getBookState()==StateData.BOOK_STATE_NORMAL) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_HAS_ENABLED);
        }
        bookInfo.setBookState(bookState);
        bookInfoMapper.updateById(bookInfo);
    }

    @Override
    @Transactional
    public void deleteBookInfo(Integer bookId) {
        BookInfo bookInfo = bookInfoMapper.selectById(bookId);
        if (bookInfo==null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_EXISTS);
        }
        if (bookInfo.getBookState()== StateData.BOOK_STATE_NORMAL) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_HAS_ENABLED);
        }
        if (bookInfo.getBookState()== StateData.BOOK_STATE_DELETED) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_HAS_DELETED);
        }
        bookInfo.setBookState(StateData.BOOK_STATE_DELETED);
        bookInfoMapper.updateById(bookInfo);
    }

    @Override
    @Transactional
    public void undeleteBookInfo(Integer bookId) {
        BookInfo bookInfo = bookInfoMapper.selectById(bookId);
        if (bookInfo==null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_EXISTS);
        }
        if (bookInfo.getBookState()!= StateData.BOOK_STATE_DELETED) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_DELETED);
        }
        bookInfo.setBookState(StateData.BOOK_STATE_DISABLED);
        bookInfoMapper.updateById(bookInfo);
    }

    @Override
    @Transactional
    public void delBookInfoBySelect(String[] bookIdsArray) {
        for (String s : bookIdsArray) {
            Integer bookId = Integer.parseInt(s);
            deleteBookInfo(bookId);
        }
    }

    @Override
    @Transactional
    public void undelBySelect(String[] bookIdsArray) {
        for (String s : bookIdsArray) {
            Integer bookId = Integer.parseInt(s);
            undeleteBookInfo(bookId);
        }
    }

    @Override
    @Transactional
    public void disableBySelect(String[] bookIdsArray) {
        for (String s : bookIdsArray) {
            Integer bookId = Integer.parseInt(s);
            updateBookState(bookId,StateData.BOOK_STATE_DISABLED);
        }
    }

    @Override
    @Transactional
    public void enableBySelect(String[] bookIdsArray) {
        for (String s : bookIdsArray) {
            Integer bookId = Integer.parseInt(s);
            updateBookState(bookId,StateData.BOOK_STATE_NORMAL);
        }
    }



    //查找出所有正常的子类
    private void findChild(Integer typeId, List<Integer> children, Integer state) {
        QueryWrapper<BookType> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id",typeId);
        if (state!=null) {
            queryWrapper.eq("type_state",StateData.BOOK_TYPE_STATE_NORMAL);
        }
        List<BookType> bookTypes = bookTypeMapper.selectList(queryWrapper);
        if (bookTypes!=null&&bookTypes.size()>0) {
            for (BookType bookType : bookTypes) {
                children.add(bookType.getTypeId());
                findChild(bookType.getTypeId(),children,StateData.BOOK_TYPE_STATE_NORMAL);
            }
        }
    }
}
